package com.len.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.len.base.CurrentUser;
import com.len.core.Principal;
import com.len.core.Utils;
import com.len.entity.SysRole;
import com.len.entity.SysRoleUser;
import com.len.entity.SysUser;
import com.len.exception.ServiceException;
import com.len.mapper.SysUserMapper;
import com.len.service.SysRoleService;
import com.len.service.SysRoleUserService;
import com.len.service.SysUserService;
import com.len.util.*;
import com.len.validator.ValidatorUtils;
import com.mybatisflex.annotation.UseDataSource;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.len.entity.table.SysRoleUserTableDef.SYS_ROLE_USER;
import static com.len.entity.table.SysUserTableDef.SYS_USER;
import static com.len.validator.ValidatorUtils.notEmpty;
import static com.len.validator.ValidatorUtils.notNull;

/**
 * 账户 service
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private static final String ADMIN = "admin";

    @Resource
    private SysRoleUserService sysRoleUserService;

    @Resource
    private SysRoleService sysRoleService;


    @Override
    public SysUser login(String username) {
        //根据用户名查询库表
        return queryChainByUsername(username).one();
    }

    /**
     * 数据源切换，编码方式实现
     * @param sysRoleUser
     * @return
     */
    @Override
    public List<SysRoleUser> selectByCondition(SysRoleUser sysRoleUser) {

        //数据源切换 编码方式实现
        DataSourceKey.use("ds2");
        return sysRoleUserService.queryChain()
                .where(SYS_ROLE_USER.USER_ID.eq(sysRoleUser.getUserId(), StrUtil.isNotEmpty(sysRoleUser.getUserId())))
                .and(SYS_ROLE_USER.ROLE_ID.eq(sysRoleUser.getRoleId(), StrUtil.isNotEmpty(sysRoleUser.getRoleId())))
                .list();
    }


    /**
     * 数据源切换，根据注解实现 不常用，主要还是 编码方式实现
     * @param user 用户对象
     * @param role 角色列表
     * @return
     */
    @Override
    @UseDataSource("dataSourceName")
    public boolean add(SysUser user, List<String> role) {
        //validateEntity(user, AddGroup.class);
        notNull(role, "role.not.null");
        if (!checkUser(user.getUsername())) {
            throw new ServiceException(MsHelper.getMsg("user.exists"));
        }
        // 密码加密
        user.setPassword(Md5Util.getMD5(user.getPassword(), user.getUsername()));
        save(user);

        SysRoleUser sysRoleUser = new SysRoleUser();
        sysRoleUser.setUserId(user.getId());
        // 角色录入
        role.forEach(item -> CompletableFuture.runAsync(() -> sysRoleUserService.save(SysRoleUser.builder().userId(user.getId()).roleId(item).build())).join());

        return true;
    }

    @Override
    public boolean updateUser(SysUser user, List<String> role) {

        //SysUser oldUser = getById(user.getId());
        //BeanUtil.copyNotNullBean(user, oldUser);
        //updateById(oldUser);

        // 更新用户信息
        updateById(user);

        // 删除原有角色集合
        if (CollUtil.isNotEmpty(role)) {
            sysRoleUserService.remove(queryChain().where(SYS_ROLE_USER.USER_ID.eq(user.getId())));
            ArrayList<SysRoleUser> roleList = new ArrayList<>();
            role.forEach(item -> roleList.add(SysRoleUser.builder().userId(user.getId()).roleId(item).build()));
            sysRoleUserService.saveBatch(roleList);
        }
        /*SysRoleUser sysRoleUser = new SysRoleUser();
        sysRoleUser.setUserId(oldUser.getId());
        List<SysRoleUser> keyList = selectByCondition(sysRoleUser);
        for (SysRoleUser currentRoleUser : keyList) {
            QueryWrapper<SysRoleUser> queryWrapper = new QueryWrapper<>(currentRoleUser);
            roleUserService.remove(queryWrapper);
        }*/

        /*if (role != null) {
            for (String r : role) {
                sysRoleUser.setRoleId(r);
                roleUserService.save(sysRoleUser);
            }
        }*/
        updateCurrent(user);
        return true;
    }

    @Override
    public boolean delById(String id, boolean realDel) {
        notEmpty(id, "failed.get.data");

        SysUser sysUser = getById(id);
        if (ADMIN.equals(sysUser.getUsername())) {
            throw new ServiceException(MsHelper.getMsg("user.del.admin"));
        }

        long count = sysRoleUserService.count(queryChain().where(SYS_ROLE_USER.USER_ID.eq(id)));

        /*SysRoleUser roleUser = new SysRoleUser();
        roleUser.setUserId(id);
        QueryWrapper<SysRoleUser> wrapper = new QueryWrapper<>(roleUser);
        int count = roleUserService.count(wrapper);*/
        if (count > 0) {
            throw new ServiceException(MsHelper.getMsg("user.bind.role"));
        }

        /*if (!realDel) {
            // 逻辑
            sysUser.setDelFlag(Byte.parseByte("1"));
            sysUserMapper.updateById(sysUser);
        } else {
            // 物理
            sysUserMapper.delById(id);
        }*/

        // 逻辑删除 @Column(isLogicDelete = true) 注解生效
        removeById(id);
        return true;
    }

    @Override
    public Boolean checkUser(String username) {
        return queryChainByUsername(username).count() <= 0;
    }

    @Override
    public List<Checkbox> getUserRoleList(String id) {

      /*  List<SysRole> roleList = roleService.list();
        SysRoleUser sysRoleUser = new SysRoleUser();
        sysRoleUser.setUserId(id);
        List<SysRoleUser> kList = selectByCondition(sysRoleUser);

        List<Checkbox> checkboxList = new ArrayList<>();
        Checkbox checkbox;
        for (SysRole sysRole : roleList) {
            checkbox = new Checkbox();
            checkbox.setId(sysRole.getId());
            checkbox.setName(sysRole.getRoleName());
            for (SysRoleUser sysRoleUser1 : kList) {
                if (sysRoleUser1.getRoleId().equals(sysRole.getId())) {
                    checkbox.setCheck(true);
                    break;
                }
            }
            checkboxList.add(checkbox);
        }*/

        List<SysRole> roleList = sysRoleService.list();
        List<SysRoleUser> kList = selectByCondition(SysRoleUser.builder().userId(id).build());
        List<Checkbox> results = new ArrayList<>();
        List<String> roleIdList = Utils.mapForList(roleList, kList);

        roleList.forEach(role -> {
            results.add(Checkbox.builder()
                    .id(role.getId())
                    .name(role.getRoleName())
                    .check(CollUtil.isNotEmpty(roleIdList) && roleIdList.contains(role.getId()))
                    .build());
        });

        /*for (SysRole sysRole : roleList) {
            checkbox = new Checkbox();
            checkbox.setId(sysRole.getId());
            checkbox.setName(sysRole.getRoleName());
            for (SysRoleUser sysRoleUser1 : kList) {
                if (sysRoleUser1.getRoleId().equals(sysRole.getId())) {
                    checkbox.setCheck(true);
                    break;
                }
            }
            checkboxList.add(checkbox);
        }*/
        return results;
    }

    @Override
    public Boolean rePass(String id, String newPwd) {
        ValidatorUtils.notEmpty(id, "failed.get.data");
        ValidatorUtils.notEmpty(newPwd, "failed.get.data");

        SysUser user = getById(id);
        newPwd = Md5Util.getMD5(newPwd, user.getUsername());
        if (newPwd.equals(user.getPassword())) {
            throw new ServiceException("newpass.not.eq.oldpass");
        }


        return updateById(SysUser.builder()
                .id(id)
                .password(newPwd)
                .build());

        //return sysUserMapper.rePass(user);
        //return 1;
    }

    @Override
    public List<SysUser> getUserByRoleId(String roleId) {
        //return sysUserMapper.getUserByRoleId(roleId);
        return list(queryChain().select(SYS_USER.ID, SYS_USER.USERNAME, SYS_USER.REAL_NAME)
                .leftJoin(SYS_ROLE_USER)
                .on(SYS_USER.ID.eq(SYS_ROLE_USER.USER_ID))
                .where(SYS_ROLE_USER.ROLE_ID.eq(roleId)));
    }

    @Override
    public void setMenuAndRoles(String username) {
    /*    SysUser s = new SysUser();
        s.setUsername(username);
        QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>(s);
        s = sysUserMapper.selectOne(userQueryWrapper);
        CurrentUser currentUser = new CurrentUser(s.getId(), s.getUsername(), s.getAge(), s.getEmail(), s.getPhoto());
        Subject subject = Principal.getSubject();
        // 角色权限封装进去
        // 根据用户获取菜单
        Session session = subject.getSession();

        List<SysMenu> menuList = menuService.getUserMenu(s.getId());
        JSONArray menuArr = menuService.getMenuJsonByUser(menuList);
        session.setAttribute("menu", menuArr);
        session.setAttribute("menuArr", menuArr.toString());

        List<CurrentMenu> currentMenuList = new ArrayList<>();
        Set<SysRole> roleList = new HashSet<>();
        for (SysMenu m : menuList) {
            CurrentMenu currentMenu = new CurrentMenu();
            BeanUtil.copyNotNullBean(m, currentMenu);
            currentMenuList.add(currentMenu);
            roleList.addAll(m.getRoleList());
        }

        List<CurrentRole> currentRoleList = new ArrayList<>();

        for (SysRole r : roleList) {
            CurrentRole role = new CurrentRole();
            BeanUtil.copyNotNullBean(r, role);
            currentRoleList.add(role);
        }
        currentUser.setCurrentRoleList(currentRoleList);
        currentUser.setCurrentMenuList(currentMenuList);
        session.setAttribute("currentPrincipal", currentUser);*/
    }

    /**
     * 更新session头像
     */
    @Override
    public void updateCurrent(SysUser sysUser) {

        CurrentUser principal = Principal.getPrincipal();
        if (principal.getId().equals(sysUser.getId())) {
            // 当前用户
            CurrentUser currentUse = Principal.getCurrentUse();
            Session session = Principal.getSession();
            currentUse.setPhoto(sysUser.getPhoto());
            session.setAttribute("currentPrincipal", currentUse);
        }

    }

    @Override
    public boolean updatePerson(SysUser user) {
        /*SysUser oldUser = getById(user.getId());
        BeanUtil.copyNotNullBean(user, oldUser);*/
        updateById(user);
        updateCurrent(user);
        return true;
    }

    private QueryChain<SysUser> queryChainByUsername(String username) {
        return queryChain().where(SYS_USER.USERNAME.eq(username));
    }
}
